Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added support for datadog via http api #67

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

savaki
Copy link

@savaki savaki commented Nov 22, 2017

initial support for datadog service. to test it with a live account, run

API_KEY=your-datdog-key go test -v

@CLAassistant
Copy link

CLAassistant commented Nov 22, 2017

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.


// New returns a new datadog reporter
func New(apiKey string, opts ...Option) (*Reporter, error) {
endpoint := "https://app.datadoghq.com/api/v1/series?api_key=" + apiKey
Copy link
Contributor

@robskillington robskillington May 9, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Want to make this URL a const at the top of this file?

Also might want use URL encoding to encode anything in the api key that needs encoding, e.g.

var params url.Values
params.Add("api_key", apiKey)
endpoint := fmt.Sprintf(endpointURL + "?" + params.Encode())

m := poolMetric.Get().(*metric)
m.Name = name
m.Type = metricType
m.Points = [][]float64{
Copy link
Contributor

@robskillington robskillington May 9, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're pooling these objects you may want to reuse the array on it. i.e.

if len(m.Points) == 1 && len(m.Points[0]) == 2 {
	m.Points[0][0] = float64(time.Now().Unix())
	m.Points[0][1] = value
} else {
	m.Points = /* construct */
}

},
}
for k, v := range tags {
m.Tags = append(m.Tags, k+":"+v)
Copy link
Contributor

@robskillington robskillington May 9, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're pooling the metric you'll have to reset the m.Tags slice at first.

e.g.

m.Tags = m.Tags[:0] // make sure slice has length zero (but retains capacity)

for k, v := range tags {
	m.Tags = append(m.Tags, k+":"+v)
}

r.metrics[r.offset] = m
r.offset++

if r.offset == r.bufSize {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need offset? Can't you simply do a len(r.metrics)? It's better to have one source of truth if possible.

}

// flush is a thread-unsafe flush. assumes caller has already obtained lock
func (r *Reporter) flush() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps rename the method flushWithLock(...) to signal that it relies on the lock, makes the code a little easier to read.

if err := r.post(data); err != nil {
fmt.Fprintln(os.Stderr, "failed to connect to host")
fmt.Fprintln(r.output, "failed to connect to host")
time.Sleep(time.Second * 15)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps make this backoff configurable?

for attempts := 0; attempts < 3; attempts++ {
if err := r.post(data); err != nil {
fmt.Fprintln(os.Stderr, "failed to connect to host")
fmt.Fprintln(r.output, "failed to connect to host")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps make where this notification goes configurable? Users may have their own logging library they wish to use, etc.

m.Points = nil
m.Type = ""
m.Host = ""
m.Tags = nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to pool this, probably better to m.Tags = m.Tags[:0]


func (m *metric) Reset() {
m.Name = ""
m.Points = nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to pool this you probably don't want to reset this slice to nil.

const (
// DefaultBufferSize contains the number of metrics the datadog reporter
// will capture before forcing a flush
DefaultBufferSize = 512
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps a larger default is ideal? 4096 or similar, which would generate probably 100kb roughly of payload I guess.

@robskillington
Copy link
Contributor

Hey savaki, thanks for the contribution.

After reviewing the change you may want to also look into flushing based on some timer in addition to your size based submission. Otherwise the last batch of metrics is unlikely to ever be submitted.

Could you make your reporter implement io.Closer so that it flushes its last submission when the tally scope is closed?

@project0
Copy link

Is there any update?

@bbuckland
Copy link

Any update on this?

@EngHabu
Copy link

EngHabu commented Nov 5, 2021

However unlikely it's, I'm just going to ask anyway... Any update on this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants